package be.artisjaap.htmlparser.core;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;

import org.ccil.cowan.tagsoup.Parser;
import org.ccil.cowan.tagsoup.XMLWriter;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public abstract class ASite {

    public abstract Collection<String> getAllUrls();

    public abstract String generateFilename(String url);

    public String getDefaultPath() {
        String path = "pages/" + this.getClass().getName().replaceAll("\\.", "/");
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        return path;
    }

    public void parsePage(File file, ISiteMapper htmlmapper) {
        SiteParser siteParser = new SiteParser();
        InputStream is;

        try {
            is = new FileInputStream(getDefaultPath() + "/" + file);
            siteParser.parse(is, htmlmapper);

        }
        catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void saveAllFromSite(boolean cache, ISiteMapper tag, Writer out) {
        for (String s : getAllUrls()) {
            String filename = generateFilename(s);
            File file = new File(getDefaultPath() + "/" + filename);
            if (file.exists() && cache) {
                readFileFromDisk(new File(file.getName()), tag, out);
            }
            else {
                readUrlToDisk(s, filename, cache);
            }
        }
    }

    protected String readUrlToDisk(String url, String filename, boolean cache) {
        // cleanup filename
        filename = filename.replaceAll("[\\'?<>/\\\\]", "");

        System.out.println("generate file: " + filename);

        if (cache) {
            File f = new File(getDefaultPath() + "/" + filename);
            if (f.exists()) return filename;
        }
        ByteArrayOutputStream out = null;
        PrintWriter pw = null;
        try {
            // read URL

            URL u = new URL(url);

            java.net.URLConnection c = u.openConnection();
            c.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");

            BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
            InputSource source = new InputSource(in);

            // convert content to xml
            out = new ByteArrayOutputStream();
            Parser parser = new Parser();
            pw = new PrintWriter(out);
            XMLWriter writer = new XMLWriter(pw);
            parser.setContentHandler(writer);
            parser.parse(source);
            pw.flush();

            // write to file
            Writer wout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getDefaultPath() + "/" + filename), "UTF-8"));
            ByteArrayInputStream ins = new ByteArrayInputStream(out.toByteArray());

            int i;
            while ((i = ins.read()) != -1) {
                wout.write((char) i);
                wout.flush();
            }

            wout.close();
            out.close();
            pw.close();
            // out.toByteArray()
        }
        catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return filename;
    }

    public void readFileFromDisk(File file, ISiteMapper tag, Writer out) {
        try {
            ISiteMapper newTag = tag.getClass().newInstance();
            parsePage(file, newTag);
            newTag.generateScript(out);
        }
        catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void readAllFromDisk(ISiteMapper tag, Writer out) {
        File productDir = new File(getDefaultPath());
        if (productDir.isDirectory()) {
            File files[] = productDir.listFiles();
            for (int i = 0; i < files.length; i++) {
                System.out.println("#" + i + " : " + files[i].getName());
                // DetailPageAegTag dpt = new DetailPageAegTag();
                readFileFromDisk(new File(files[i].getName()), tag, out);
            }
        }
    }

    @Deprecated
    private static void writeWebContent(InputStream content, String file) {
        try {
            OutputStream out = new FileOutputStream(new File(file));

            byte buf[] = new byte[1024];
            int len;
            while ((len = content.read(buf)) > 0)
                out.write(buf, 0, len);
            out.close();
            content.close();

            out.flush();
            out.close();
        }
        catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
